import logging
from typing import Dict, List, Any, Optional
from sqlalchemy.orm import Session
from app.models.api_service import APIService, APICallLog, APIStatus
from app.models.datasource import DataSource
from app.utils.doris_client import DorisClient, get_doris_client
from app.database import get_db
from datetime import datetime
import json
import time

logger = logging.getLogger(__name__)


class DataAPIService:
    """数据 API 服务"""
    
    def __init__(self, db: Session):
        self.db = db
        self.doris_client = get_doris_client()
    
    def create_api_service(self, api_data: Dict[str, Any]) -> APIService:
        """创建 API 服务"""
        api_service = APIService(**api_data)
        self.db.add(api_service)
        self.db.commit()
        self.db.refresh(api_service)
        return api_service
    
    def execute_api_query(self, api_id: int, params: Dict[str, Any] = None, 
                         request_info: Dict[str, Any] = None) -> Dict[str, Any]:
        """执行 API 查询"""
        start_time = time.time()
        
        # 获取 API 服务配置
        api_service = self.db.query(APIService).filter(APIService.id == api_id).first()
        if not api_service:
            return {"error": "API 服务不存在", "status_code": 404}
        
        if api_service.status != APIStatus.PUBLISHED:
            return {"error": "API 服务未发布", "status_code": 403}
        
        # 创建调用日志
        call_log = APICallLog(
            api_service_id=api_id,
            client_ip=request_info.get("client_ip") if request_info else None,
            user_id=request_info.get("user_id") if request_info else None,
            request_method=request_info.get("method", "GET") if request_info else "GET",
            request_path=request_info.get("path", "") if request_info else "",
            request_params=params,
            request_headers=request_info.get("headers") if request_info else None
        )
        
        try:
            # 执行查询
            result = self._execute_query_logic(api_service, params or {})
            
            # 记录成功调用
            call_log.response_status = 200
            call_log.response_time = int((time.time() - start_time) * 1000)  # 毫秒
            call_log.response_size = len(json.dumps(result, ensure_ascii=False).encode('utf-8'))
            
            self.db.add(call_log)
            self.db.commit()
            
            return {
                "data": result,
                "status_code": 200,
                "message": "查询成功"
            }
            
        except Exception as e:
            # 记录失败调用
            call_log.response_status = 500
            call_log.response_time = int((time.time() - start_time) * 1000)
            call_log.error_message = str(e)
            
            self.db.add(call_log)
            self.db.commit()
            
            logger.error(f"API 查询执行失败: {str(e)}")
            return {
                "error": "查询执行失败",
                "status_code": 500,
                "details": str(e)
            }
    
    def _execute_query_logic(self, api_service: APIService, params: Dict[str, Any]) -> List[Dict[str, Any]]:
        """执行具体的查询逻辑"""
        try:
            # 获取数据源
            if api_service.datasource_id:
                datasource = self.db.query(DataSource).filter(
                    DataSource.id == api_service.datasource_id
                ).first()
                
                if datasource and datasource.source_type.value == "doris":
                    # 使用 Doris 客户端执行查询
                    return self._execute_doris_query(api_service, params)
            
            # 默认使用配置的 Doris 数据仓库
            return self._execute_doris_query(api_service, params)
            
        except Exception as e:
            logger.error(f"查询逻辑执行失败: {str(e)}")
            raise
    
    def _execute_doris_query(self, api_service: APIService, params: Dict[str, Any]) -> List[Dict[str, Any]]:
        """在 Doris 数据仓库中执行查询"""
        if not api_service.query_sql:
            raise ValueError("未配置查询 SQL")
        
        # 参数替换
        query_sql = self._replace_query_parameters(api_service.query_sql, params, api_service)
        
        # 添加行数限制
        if api_service.max_rows and api_service.max_rows > 0:
            if "LIMIT" not in query_sql.upper():
                query_sql += f" LIMIT {api_service.max_rows}"
        
        # 执行查询
        result = self.doris_client.execute_query(query_sql, params)
        
        # 应用响应格式配置
        if api_service.response_format:
            result = self._format_response(result, api_service.response_format)
        
        return result
    
    def _replace_query_parameters(self, sql: str, params: Dict[str, Any], 
                                 api_service: APIService) -> str:
        """替换查询中的参数"""
        try:
            # 获取参数配置
            param_config = api_service.request_params
            if isinstance(param_config, str):
                param_config = json.loads(param_config)
            
            if not param_config:
                return sql
            
            # 验证必需参数
            for param_name, param_info in param_config.items():
                if param_info.get("required", False) and param_name not in params:
                    raise ValueError(f"缺少必需参数: {param_name}")
                
                # 参数类型验证
                if param_name in params:
                    param_value = params[param_name]
                    param_type = param_info.get("type", "string")
                    
                    if param_type == "int" and not isinstance(param_value, int):
                        try:
                            params[param_name] = int(param_value)
                        except ValueError:
                            raise ValueError(f"参数 {param_name} 类型错误，期望 int")
                    elif param_type == "float" and not isinstance(param_value, (int, float)):
                        try:
                            params[param_name] = float(param_value)
                        except ValueError:
                            raise ValueError(f"参数 {param_name} 类型错误，期望 float")
            
            # 替换 SQL 中的参数占位符
            for param_name, param_value in params.items():
                placeholder = f"${{{param_name}}}"
                if placeholder in sql:
                    # 根据参数类型进行适当的引用
                    if isinstance(param_value, str):
                        sql = sql.replace(placeholder, f"'{param_value}'")
                    else:
                        sql = sql.replace(placeholder, str(param_value))
            
            return sql
            
        except Exception as e:
            logger.error(f"参数替换失败: {str(e)}")
            raise
    
    def _format_response(self, data: List[Dict[str, Any]], 
                        format_config: Dict[str, Any]) -> List[Dict[str, Any]]:
        """格式化响应数据"""
        try:
            if isinstance(format_config, str):
                format_config = json.loads(format_config)
            
            if not format_config:
                return data
            
            # 字段重命名
            if "field_mapping" in format_config:
                field_mapping = format_config["field_mapping"]
                formatted_data = []
                
                for record in data:
                    formatted_record = {}
                    for original_field, new_field in field_mapping.items():
                        if original_field in record:
                            formatted_record[new_field] = record[original_field]
                    formatted_data.append(formatted_record)
                
                return formatted_data
            
            # 字段过滤
            if "include_fields" in format_config:
                include_fields = format_config["include_fields"]
                filtered_data = []
                
                for record in data:
                    filtered_record = {field: record[field] 
                                     for field in include_fields 
                                     if field in record}
                    filtered_data.append(filtered_record)
                
                return filtered_data
            
            return data
            
        except Exception as e:
            logger.error(f"响应格式化失败: {str(e)}")
            return data
    
    def test_api_query(self, api_id: int, test_params: Dict[str, Any] = None) -> Dict[str, Any]:
        """测试 API 查询"""
        try:
            api_service = self.db.query(APIService).filter(APIService.id == api_id).first()
            if not api_service:
                return {"error": "API 服务不存在"}
            
            # 执行测试查询（限制返回行数）
            test_sql = api_service.query_sql
            if test_sql and "LIMIT" not in test_sql.upper():
                test_sql += " LIMIT 10"  # 测试时限制 10 行
            
            # 临时创建一个测试 API 服务对象
            test_api = APIService(
                query_sql=test_sql,
                request_params=api_service.request_params,
                response_format=api_service.response_format,
                max_rows=10
            )
            
            result = self._execute_doris_query(test_api, test_params or {})
            
            return {
                "success": True,
                "data": result,
                "row_count": len(result),
                "message": "测试查询成功"
            }
            
        except Exception as e:
            logger.error(f"API 测试失败: {str(e)}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def get_api_call_stats(self, api_id: int, days: int = 7) -> Dict[str, Any]:
        """获取 API 调用统计"""
        try:
            from datetime import timedelta
            end_date = datetime.now()
            start_date = end_date - timedelta(days=days)
            
            # 查询调用记录
            call_logs = self.db.query(APICallLog).filter(
                APICallLog.api_service_id == api_id,
                APICallLog.call_time >= start_date,
                APICallLog.call_time <= end_date
            ).all()
            
            # 统计数据
            total_calls = len(call_logs)
            success_calls = len([log for log in call_logs if log.response_status == 200])
            failed_calls = total_calls - success_calls
            
            avg_response_time = 0
            if call_logs:
                valid_times = [log.response_time for log in call_logs if log.response_time]
                if valid_times:
                    avg_response_time = sum(valid_times) / len(valid_times)
            
            return {
                "total_calls": total_calls,
                "success_calls": success_calls,
                "failed_calls": failed_calls,
                "success_rate": (success_calls / total_calls * 100) if total_calls > 0 else 0,
                "avg_response_time": round(avg_response_time, 2),
                "period_days": days
            }
            
        except Exception as e:
            logger.error(f"获取 API 统计失败: {str(e)}")
            return {"error": str(e)}
    
    def get_doris_table_preview(self, table_name: str, limit: int = 100) -> Dict[str, Any]:
        """预览 Doris 表数据"""
        try:
            # 获取表结构
            schema = self.doris_client.get_table_schema(table_name)
            
            # 获取样例数据
            query = f"SELECT * FROM {table_name} LIMIT {limit}"
            data = self.doris_client.execute_query(query)
            
            # 获取统计信息
            stats = self.doris_client.get_table_stats(table_name)
            
            return {
                "table_name": table_name,
                "schema": schema,
                "sample_data": data,
                "stats": stats,
                "preview_rows": len(data)
            }
            
        except Exception as e:
            logger.error(f"预览表数据失败: {str(e)}")
            return {"error": str(e)}


def get_data_api_service(db: Session = None) -> DataAPIService:
    """获取数据 API 服务实例"""
    if db is None:
        db = next(get_db())
    return DataAPIService(db) 